package com.yilin.tms.order.service.order.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yilin.commons.exception.BusinessException;
import com.yilin.commons.util.ArrayUtil;
import com.yilin.commons.util.CommonUtil;
import com.yilin.commons.util.DateTimeUtil;
import com.yilin.commons.util.StringUtil;
import com.yilin.tms.core.commons.base.BaseEntity;
import com.yilin.tms.core.commons.utils.OrderUtil;
import com.yilin.tms.core.application.PageData;
import com.yilin.tms.core.commons.utils.ParamUtil;
import com.yilin.tms.core.entity.order.goods.GoodsOrderNote;
import com.yilin.tms.core.entity.order.goods.GoodsOrderNoteDetail;
import com.yilin.tms.core.entity.order.goods.GoodsOrder;
import com.yilin.tms.core.entity.order.payment.OrderPaymentCost;
import com.yilin.tms.core.entity.order.rob.RobOrder;
import com.yilin.tms.core.entity.order.transit.TransitOrder;
import com.yilin.tms.core.entity.system.param.GoodsType;
import com.yilin.tms.core.entity.user.UserType;
import com.yilin.tms.core.commons.model.CalculateCost;
import com.yilin.tms.core.entity.user.organize.MemberType;
import com.yilin.tms.core.entity.user.organize.Organize;
import com.yilin.tms.core.entity.user.account.Account;
import com.yilin.tms.order.mapper.goods.GoodsOrderMapper;
import com.yilin.tms.order.mapper.goods.GoodsOrderNoteDetailMapper;
import com.yilin.tms.order.mapper.goods.GoodsOrderNoteMapper;
import com.yilin.tms.order.service.order.IDispatchService;
import com.yilin.tms.order.service.order.ITransitService;
import com.yilin.tms.order.service.owner.IGoodsOwnerService;
import com.yilin.tms.order.service.order.IGoodsService;
import com.yilin.tms.order.service.order.IRobService;
import com.yilin.tms.order.service.payment.ICalculationService;
import com.yilin.tms.order.service.payment.IOrderPaymentCostService;
import com.yilin.tms.order.service.payment.IOrderRefundCostService;

import com.yilin.tms.core.remote.IMessageRemote;
import com.yilin.tms.core.remote.ISystemRemote;
import com.yilin.tms.core.remote.IUserRemote;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.transaction.Transactional;
import java.util.*;

/**
 * 货源Service
 *
 * @author zhangjinyuan
 * @date 2022/10/29
 */
@Service
@Transactional(rollbackOn = Exception.class)
public class GoodsService extends ServiceImpl<GoodsOrderMapper, GoodsOrder> implements IGoodsService {

    private Logger logger = LoggerFactory.getLogger(GoodsService.class);

    @Resource
    IGoodsOwnerService goodsOwnerService;
    @Resource
    IRobService robService;
    @Resource
    ITransitService transitService;
    @Resource
    IOrderPaymentCostService orderPaymentService;
    @Resource
    IOrderRefundCostService orderRefundCostService;
    @Resource
    ICalculationService calculationService;
    @Resource
    IDispatchService dispatchService;

    @Resource
    IMessageRemote messageRemote;
    @Resource
    IUserRemote userRemote;
    @Resource
    ISystemRemote systemRemote;

    @Resource
    GoodsOrderMapper goodsOrderMapper;
    @Resource
    GoodsOrderNoteMapper goodsOrderNoteMapper;
    @Resource
    GoodsOrderNoteDetailMapper goodsOrderNoteDetailMapper;


    /**
     * 获取货源列表
     * 排序时sort!=null，筛选时query!=null，按离我最近排序时position!=null
     */
    @Override
    public PageData<GoodsOrder> getGoodsOrderPage(Account loginUser, GoodsOrder query, Integer page, Integer limit) {
        List<Integer> statuses = new ArrayList<>();
        if (query.getQueryStatuses() != null && query.getQueryStatuses().length > 0) {
            List<GoodsOrder.GoodsStatus> statusList = Arrays.asList(query.getQueryStatuses());
            statuses = ArrayUtil.fieldAdd(statusList, obj -> obj.index);
        }
        PageData<GoodsOrder> pageData = new PageData<>(page, limit);
        if (StringUtil.isEmpty(query.getTargetPosition())) pageData.addOrder(OrderItem.desc("create_time"));
        //查询和车主存在合作的货主
        if (loginUser.getUserType() == UserType.truckerUser) {
            List<String> stringList = ParamUtil.isSuccess(userRemote.getCooperateShipperIdList(loginUser.getOrganizeId()));
            query.setCooperateShipperIds(ArrayUtil.join(stringList, ","));
            Organize organize = ParamUtil.isSuccess(userRemote.getOrganizeById(loginUser.getSuperiorPlatId()));
            query.setQueryTruckerPlatId(organize.getId());
            query.setQueryTruckerZonePlatId(organize.getSuperiorPlatOrganizeId());
        }
        PageData<GoodsOrder> orderPageData = goodsOrderMapper.getGoodsOrderPage(pageData, loginUser, query, statuses);
        //批量获取个点的预付单
        List<String> idList = ArrayUtil.fieldAdd(orderPageData.getList(), BaseEntity::getId);
        if (!idList.isEmpty()) {
            List<OrderPaymentCost> goodsPaymentList = orderPaymentService.getOrderPaymentByGoodsOrderIds(idList);
            for (GoodsOrder goodsOrder : orderPageData.getList()) {
                OrderPaymentCost goodsPayment = ArrayUtil.getBy(goodsPaymentList, obj -> obj.getGoodsOrderId().equals(goodsOrder.getId()));
                //货主前台操作标识
                goodsOwnerService.getCanOperationMark(loginUser, goodsOrder, goodsPayment);
                //获取货源详情链接
                goodsOrder.setGoodsOrderDetailUrl(goodsOwnerService.getGoodsOrderDetailUrl(goodsOrder.getId()));
            }
        }

        return orderPageData;
    }

    /**
     * 获取货源详情
     */
    @Override
    public GoodsOrder getGoodsOrderDetail(Account loginUser, String goodsOrderId) {
        GoodsOrder goodsOrder = goodsOrderMapper.selectById(goodsOrderId);
        if (goodsOrder == null) throw new BusinessException("未查询到该货源");
        QueryWrapper<GoodsOrderNote> wrapper = new QueryWrapper<GoodsOrderNote>().eq("goods_order_id", goodsOrderId);
        List<GoodsOrderNote> goodsOrderNoteList = goodsOrderNoteMapper.selectList(wrapper);
        goodsOrderNoteList.forEach(goodsOrderNote -> {
            QueryWrapper<GoodsOrderNoteDetail> detailQueryWrapper = new QueryWrapper<>();
            detailQueryWrapper.eq("goods_order_note_id", goodsOrderNote.getId());
            goodsOrderNote.setGoodsOrderNoteDetailList(goodsOrderNoteDetailMapper.selectList(detailQueryWrapper));
        });
        goodsOrder.setGoodsOrderNoteList(goodsOrderNoteList);
        //前台操作标识
        OrderPaymentCost goodsPayment = orderPaymentService.getOrderPaymentByGoodsOrderId(goodsOrderId);
        goodsOwnerService.getCanOperationMark(loginUser, goodsOrder, goodsPayment);
        //获取货源详情链接
        goodsOrder.setGoodsOrderDetailUrl(goodsOwnerService.getGoodsOrderDetailUrl(goodsOrder.getId()));
        return goodsOrder;
    }

    /**
     * 获取货单列表 公共
     * 隐藏敏感信息
     */
    @Override
    public PageData<GoodsOrder> getPublicGoodsOrderPage(GoodsOrder query, Integer start, Integer limit) {
        List<Integer> statuses = new ArrayList<>();
        statuses.add(GoodsOrder.GoodsStatus.release.index);
        PageData<GoodsOrder> pageData = goodsOrderMapper.getGoodsOrderPage(new PageData<>(start, limit), new Account(), query, statuses);
        if (ArrayUtil.isNotEmpty(pageData.getList())) {
            pageData.getList().forEach(goodsOrderView -> {
                //隐藏敏感信息
                goodsOwnerService.goodsPrivateData(goodsOrderView);
                //获取货源详情链接
                goodsOrderView.setGoodsOrderDetailUrl(goodsOwnerService.getGoodsOrderDetailUrl(goodsOrderView.getId()));
            });
        } else {
            pageData.setList(new ArrayList<>());
        }
        return pageData;
    }


    /**
     * 货主推送货源给车主
     */
    @Override
    public void pushGoodOrderToTrucker(Account loginUser, GoodsOrder goodsOrder, Account truckerAccount) {
        OrderUtil.verifySaveGoodsPush(loginUser.getId());
        //货源详情链接
        goodsOrder.setGoodsOrderDetailUrl(goodsOwnerService.getGoodsOrderDetailUrl(goodsOrder.getId()));
        String format = String.format("尊敬的车主用户您好，货主用户：%s %s 向您推荐了一条货源信息，货单号：%s，赶紧前往看看吧！", loginUser.getOrganizeName(), loginUser.getName(), goodsOrder.getGoodsOrderNo());
        messageRemote.sendOrderNotify(truckerAccount.getId(), format, goodsOwnerService.getGoodsOrderDetailUrl(goodsOrder.getId()));
    }

    /**
     * 主流程：保存货源
     */
    @Override
    public GoodsOrder saveGoodsOrder(Account loginUser, GoodsOrder goodsOrder) {
        List<GoodsOrderNote> goodsOrderNoteList = goodsOrder.getGoodsOrderNoteList();
        //###补充货源基础信息
        goodsOrder.setTitle(OrderUtil.genOrderTitle(ArrayUtil.first(goodsOrderNoteList)));
        fillInBasicData(loginUser, goodsOrder, goodsOrderNoteList);
        //###检查发货节点、货物信息、货物量
        goodsOrderNoteList.forEach(goodsOrderNote -> {
            checkGoodsOrderNote(goodsOrderNote);
            List<GoodsOrderNoteDetail> noteDetailList = goodsOrderNote.getGoodsOrderNoteDetailList();
            ArrayUtil.forEach(noteDetailList, goodsNoteDetail -> checkGoodsInfo(goodsOrder, goodsNoteDetail));
        });
        //###检查货源费用,包括手续费，运输费，保费等
        calculateOrderCost(goodsOrder);
        goodsOrderMapper.insert(goodsOrder);
        //保存货物信息
        saveNoteDetail(loginUser, goodsOrder);
        //生成货源费用预付单
        OrderPaymentCost orderPaymentCost = orderPaymentService.generateGoodsOrderPayment(goodsOrder);
        goodsOrder.setPayCost(orderPaymentCost.getPayCost());
        goodsOrderMapper.updateById(goodsOrder);
        return goodsOrder;
    }

    /**
     * 货源上线
     */
    @Override
    public void releaseGoodsOrder(Account loginUser, GoodsOrder goodsOrder) {
        //预约时间为null直接上线
        goodsOrder.setGoodsStatus(GoodsOrder.GoodsStatus.release);
        goodsOrder.setReleaseTime(new Date());
        //货源首次上线推送
        if ((goodsOrder.getReleaseNumber() == 0) && StringUtil.isNotEmpty(goodsOrder.getTruckTypeIds())) {
            goodsOrder.setReleaseNumber(goodsOrder.getReleaseNumber() + 1);
//            String[] userIds = ParamUtil.isSuccess(vehicleRemote.getTruckUserListByCommTruckType(goodsOrder.getTruckTypeIds()));
//            if (userIds != null && userIds.length > 0) {
//                for (String userId : userIds) {
//                    messageRemote.sendNotificationByUser(userId, MessageData.MessageType.notice, MessageData.DataType.order,
//                            "有新的货源上线了！请打开APP查看", goodsOwnerService.getGoodsOrderDetailUrl(goodsOrder.getId()));
//                }
//            }
        }
        goodsOrderMapper.updateById(goodsOrder);
    }

    /**
     * 货源下线
     */
    @Override
    public void recallGoodsOrder(Account loginUser, GoodsOrder goodsOrder) {
        goodsOrder.setGoodsStatus(GoodsOrder.GoodsStatus.save);
        goodsOrder.setUpdateUserId(loginUser.getId());
        goodsOrder.setUpdateTime(new Date());
        goodsOrderMapper.updateById(goodsOrder);
    }

    /**
     * 货源下线2
     */
    @Override
    public void recallGoodsOrderByOrganizeId(String organizeId) {
        UpdateWrapper<GoodsOrder> updateWrapper = new UpdateWrapper<>();
        updateWrapper.in("goods_status", ArrayUtil.initList(GoodsOrder.GoodsStatus.reserve, GoodsOrder.GoodsStatus.release));
        updateWrapper.eq("shipper_organize_id", organizeId);
        updateWrapper.set("goods_status", GoodsOrder.GoodsStatus.save);
        goodsOrderMapper.update(null, updateWrapper);
    }

    /**
     * 货源下线3
     */
    @Override
    public void recallGoodsOrderByAccountId(String accountId) {
        UpdateWrapper<GoodsOrder> updateWrapper = new UpdateWrapper<>();
        updateWrapper.in("goods_status", ArrayUtil.initList(GoodsOrder.GoodsStatus.release, GoodsOrder.GoodsStatus.reserve));
        updateWrapper.eq("shipper_account_id", accountId);
        updateWrapper.set("goods_status", GoodsOrder.GoodsStatus.save);
        goodsOrderMapper.update(null, updateWrapper);
    }

    /**
     * 货源作废
     */
    @Override
    public void scrapGoodsOder(Account loginUser, GoodsOrder goodsOrder) {
        goodsOrder.setScrapTime(new Date());
        goodsOrder.setUpdateTime(new Date());
        goodsOrder.setUpdateUserId(loginUser.getId());
        goodsOrder.setGoodsStatus(GoodsOrder.GoodsStatus.scrap);
        //作废已提交的抢单
        robService.updateRobByGoodsStatus(goodsOrder.getId(), RobOrder.RobStatus.back, loginUser);
        //生成货单退款单
        OrderPaymentCost paymentCost = orderPaymentService.getOrderPaymentByGoodsOrderId(goodsOrder.getId());
        if (paymentCost != null) {
            if (paymentCost.getPayStatus() == OrderPaymentCost.PayStatus.wait) {
                throw new BusinessException("您的预支付单已发起支付，交易结果未知，无法作废货源");
            }
            if (paymentCost.getPayStatus() == OrderPaymentCost.PayStatus.complete) {
                orderRefundCostService.generateGoodsOrderRefund(goodsOrder);
            } else {
                orderPaymentService.cancelOrderPayment(paymentCost.getId(), loginUser);
            }
        }
        goodsOrderMapper.updateById(goodsOrder);
    }

    /**
     * 货源移除
     */
    @Override
    public void deleteGoodsOrder(Account loginUser, GoodsOrder goodsOrder) {
        if (goodsOrder.getGoodsStatus() != GoodsOrder.GoodsStatus.scrap) throw new BusinessException("只能删除作废单");
        //如果存在抢单成功的订单，暂时也不允许删除
        List<RobOrder> robOrderList = robService.getRobSuccessListByGoodsOrderId(goodsOrder.getId());
        if (robOrderList.size() > 0) throw new BusinessException("暂时不允许删除，因为您的货源下有待车主确认的抢单");
        goodsOrder.setScrapTime(new Date());
        goodsOrder.setUpdateTime(new Date());
        goodsOrder.setUpdateUserId(loginUser.getId());
        goodsOrderMapper.deleteById(goodsOrder);
    }

    /**
     * 单号查找
     */
    @Override
    public GoodsOrder getGoodsOrderByNo(String goodsOrderNo) {
        QueryWrapper<GoodsOrder> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("goods_order_no", goodsOrderNo);
        return goodsOrderMapper.selectOne(queryWrapper);
    }

    @Override
    public List<GoodsOrder> getGoodsOrderListByDispatchOrderId(String dispatchOrderId) {
        QueryWrapper<GoodsOrder> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("dispatch_order_id", dispatchOrderId);
        return goodsOrderMapper.selectList(queryWrapper);
    }

    /**
     * 获取存在的未作废货单
     */
    @Override
    public List<GoodsOrder> getRunGoodsOrderListByAccountId(String accountId) {
        QueryWrapper<GoodsOrder> queryWrapper = new QueryWrapper<>();
        List<Integer> list = ArrayUtil.initList(GoodsOrder.GoodsStatus.save.index, GoodsOrder.GoodsStatus.reserve.index, GoodsOrder.GoodsStatus.release.index);
        queryWrapper.in("goods_status", list);
        queryWrapper.eq("shipper_account_id", accountId);
        return goodsOrderMapper.selectList(queryWrapper);
    }

    /**
     * 获取存在的未作废货单2
     */
    @Override
    public List<GoodsOrder> getRunGoodsOrderListByOrganizeId(String organizeId) {
        QueryWrapper<GoodsOrder> queryWrapper = new QueryWrapper<>();
        List<Integer> list = ArrayUtil.initList(GoodsOrder.GoodsStatus.save.index, GoodsOrder.GoodsStatus.reserve.index, GoodsOrder.GoodsStatus.release.index);
        queryWrapper.in("goods_status", list);
        queryWrapper.eq("shipper_organize_id", organizeId);
        return goodsOrderMapper.selectList(queryWrapper);
    }

    /**
     * 定时任务 货源自动上线
     */
    @Override
    public void timerReleaseGoodsOrder() {
        QueryWrapper<GoodsOrder> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("goods_status", GoodsOrder.GoodsStatus.reserve.index);
        queryWrapper.le("reserve_time", new Date());
        List<GoodsOrder> list = list(queryWrapper);
        if (ArrayUtil.isEmpty(list)) return;
//        list.forEach(goodsOrder -> {
//            Organize platOrganize = ParamUtil.isSuccess(userRemote.getOrganizeById(goodsOrder.getPlatId()));
//            Account platManagerUser = ParamUtil.isSuccess(userRemote.getAccountById(platOrganize.getManagerUserId()));
//            goodsOrder.setReserveTime(null);
//            releaseGoodsOrder(platManagerUser, goodsOrder);
//        });
    }

    /**
     * 定时任务 货源自动下线
     */
    @Override
    public void timerRecallGoodsOrder() {
        QueryWrapper<GoodsOrder> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("goods_status", GoodsOrder.GoodsStatus.release.index);
        queryWrapper.le("end_time", new Date());
        List<GoodsOrder> list = list(queryWrapper);
        if (ArrayUtil.isEmpty(list)) return;
        list.forEach(goodsOrder -> {
//            Organize platOrganize = ParamUtil.isSuccess(userRemote.getOrganizeById(goodsOrder.getPlatId()));
//            Account platManagerUser = ParamUtil.isSuccess(userRemote.getAccountById(platOrganize.getManagerUserId()));
//            recallGoodsOrder(platManagerUser, goodsOrder);
        });
    }

    /**
     * 获取货源运输状态
     *
     * @param goodsOrderNo 货单号，多个货单","隔开
     * @return HashMap<货单号, 是否完成运输>
     */
    @Override
    public HashMap<String, Boolean> orderTransportState(String goodsOrderNo) {
        HashMap<String, Boolean> map = new HashMap<>();
        String[] goodsOrderNos = goodsOrderNo.split(",");
        for (String orderNo : goodsOrderNos) {
            boolean complete = false;
            QueryWrapper<TransitOrder> qw = new QueryWrapper<>();
            qw.eq("goods_order_no", orderNo);
            List<TransitOrder> list = transitService.list(qw);
            for (TransitOrder transitOrder : list) {
                complete = transitOrder.getTransitStatus() == TransitOrder.TransitStatus.waitingSettlement || transitOrder.getTransitStatus() == TransitOrder.TransitStatus.complete;
                if (complete) {
                    break;
                }
            }
            map.put(orderNo, complete);
        }
        return map;
    }

    /**
     * 通过WMS生成货源并分配
     */
    @Override
    public String wmsSaveGoodsOrder(Account loginUser, GoodsOrder goodsOrder) {
        //完善货源
        Organize shipperOrganize = ParamUtil.isSuccess(userRemote.getOrganizeById(loginUser.getOrganizeId()));
        addShipperData(goodsOrder, loginUser, shipperOrganize);
        addTransportType(goodsOrder);
        addShipperMemberConfig(goodsOrder, shipperOrganize);
        //完善货物节点信息
        for (GoodsOrderNote goodsOrderNote : goodsOrder.getGoodsOrderNoteList()) {
            for (GoodsOrderNoteDetail noteDetail : goodsOrderNote.getGoodsOrderNoteDetailList()) {
                List<GoodsType> typeList = ParamUtil.isSuccess(systemRemote.getGoodsTypeByCode(noteDetail.getGoodsTypeCode()));
                for (GoodsType goodsType : typeList) {
                    if (Objects.equals(goodsType.getName(), noteDetail.getGoodsTypeName())) {
                        noteDetail.setGoodsTypeId(goodsType.getId());
                        break;
                    }
                }
            }
        }
        //保存货源
        saveGoodsOrder(loginUser, goodsOrder);
        //生成抢单信息
        RobOrder robOrder = dispatchService.genRobOrder(goodsOrder);
        //分配抢单
        Organize robOrganize = ParamUtil.isSuccess(userRemote.getOrganizeById(goodsOrder.getRobOrganizeId()));
        Account robAccount = ParamUtil.isSuccess(userRemote.getAccountById(robOrganize.getManagerUserId()));
        robOrder.setRobOrganizeId(robOrganize.getId());
        robService.assignGoodsOder(loginUser, robOrder, goodsOrder, robOrganize, robAccount);
        return goodsOrder.getGoodsOrderNo();
    }


    /**
     * 内部 添加货主会员配置
     *
     * @param goodsOrder      货源
     * @param shipperOrganize 货主组织
     */
    private void addShipperMemberConfig(GoodsOrder goodsOrder, Organize shipperOrganize) {
        MemberType memberType = ParamUtil.isSuccess(userRemote.getMyMemberTypeByOrganizeId(shipperOrganize.getId()));
        goodsOrder.setReleasePaymentRate(memberType.getReleasePaymentRate());
        goodsOrder.setRobPaymentRate(memberType.getRobPaymentRate());
        goodsOrder.setDeliverPaymentRate(memberType.getDeliverPaymentRate());
        goodsOrder.setArrivalPaymentRate(memberType.getArrivalPaymentRate());
        goodsOrder.setShipperFeeRate(memberType.getShipperCarrierFeeRate());
        goodsOrder.setShipperTaxRate(memberType.getOwnerTaxRate());
        goodsOrder.setInsuranceRate(memberType.getInsuranceRate());
    }

    /**
     * 内部 添加货源运输信息
     */
    private void addTransportType(GoodsOrder goodsOrder) {
        if (goodsOrder.getGoodsOrderType() == GoodsOrder.GoodsOrderType.ordinaryOrder) {
            goodsOrder.setTitle("大宗物流");
            goodsOrder.setTransportTypeId("4028808270f1aeaf0170f1c24e4d0010");
            goodsOrder.setTransportTypeName("干线普货运输");
            goodsOrder.setTransportTypeCode("1002996");
        } else if (goodsOrder.getGoodsOrderType() == GoodsOrder.GoodsOrderType.warehouseDistribute) {
            goodsOrder.setTitle("城乡配送");
            goodsOrder.setTransportTypeId("4028808270f1aeaf0170f1d374170016");
            goodsOrder.setTransportTypeName("城市配送");
            goodsOrder.setTransportTypeCode("1003997");
        } else if (goodsOrder.getGoodsOrderType() == GoodsOrder.GoodsOrderType.warehouseCollect) {
            goodsOrder.setTitle("零担集采");
            goodsOrder.setTransportTypeId("4028808270f1aeaf0170f1d307c60014");
            goodsOrder.setTransportTypeName("集装箱运输");
            goodsOrder.setTransportTypeCode("1002998");
        }
    }

    /**
     * 内部 添加货源货主信息
     *
     * @param goodsOrder      货源对象
     * @param ShipperAccount  货主
     * @param shipperOrganize 货主组织
     */
    private void addShipperData(GoodsOrder goodsOrder, Account ShipperAccount, Organize shipperOrganize) {
        goodsOrder.setShipperOrganizeLogo(shipperOrganize.getOrganizeLogo());
        goodsOrder.setShipperOrganizeId(shipperOrganize.getId());
        goodsOrder.setShipperOrganizeName(shipperOrganize.getOrganizeName());
        goodsOrder.setShipperOrganizeType(shipperOrganize.getOrganType());
        goodsOrder.setShipperMemberTypeName(shipperOrganize.getMemberTypeName());
        goodsOrder.setShipperMonthlyRating(shipperOrganize.getMonthlyRating());
        goodsOrder.setShipperGroupOrganizeId(shipperOrganize.getGroupOrganizeId());
        goodsOrder.setShipperGroupOrganizeName(shipperOrganize.getGroupOrganizeName());
        goodsOrder.setShipperAccountId(ShipperAccount.getId());
        goodsOrder.setShipperAccountAvatar(ShipperAccount.getAvatar());
        goodsOrder.setShipperAccountName(ShipperAccount.getName());
        goodsOrder.setShipperAccountPhone(ShipperAccount.getPhone());
    }

    //### 补充货源基础信息
    private void fillInBasicData(Account loginUser, GoodsOrder goodsOrder, List<GoodsOrderNote> goodsOrderNoteList) {
        Account shipperAccount = ParamUtil.isSuccess(userRemote.getAccountById(loginUser.getId()));
        Organize shipperOrganize = ParamUtil.isSuccess(userRemote.getOrganizeById(shipperAccount.getOrganizeId()));
        Organize platformOrganize = ParamUtil.isSuccess(userRemote.getOrganizeById(shipperOrganize.getSuperiorPlatOrganizeId()));
        Organize zoneOrganize = ParamUtil.isSuccess(userRemote.getOrganizeById(platformOrganize.getSuperiorPlatOrganizeId()));
        MemberType shipperMemberType = ParamUtil.isSuccess(userRemote.getMyMemberTypeByOrganizeId(shipperOrganize.getId()));
        //平台信息
//        goodsOrder.setZonePlatId(zoneOrganize.getId());
//        goodsOrder.setZonePlatName(zoneOrganize.getOrganizeName());
//        goodsOrder.setPlatId(platformOrganize.getId());
//        goodsOrder.setPlatName(platformOrganize.getOrganizeName());
        //基础信息
        goodsOrder.setGoodsOrderNo(DateTimeUtil.dateNo("DG"));
        if (goodsOrder.getGoodsStatus() == null) goodsOrder.setGoodsStatus(GoodsOrder.GoodsStatus.save);
        goodsOrder.setSupplementCount(0);
        goodsOrder.setReleaseNumber(0);
        goodsOrder.setCreateTime(new Date());
        goodsOrder.setAddUserId(loginUser.getId());
        //货主信息
        addShipperData(goodsOrder, shipperAccount, shipperOrganize);
        //默认显示地区
        GoodsOrderNote firstGoodsOrderNote = ArrayUtil.first(goodsOrderNoteList);
        goodsOrder.setDisplayConsignorArea(firstGoodsOrderNote.getConsignorArea());
        goodsOrder.setDisplayConsignorCoordinate(firstGoodsOrderNote.getConsignorCoordinate());
        goodsOrder.setDisplayConsigneeArea(firstGoodsOrderNote.getConsigneeArea());
        goodsOrder.setDisplayConsigneeCoordinate(firstGoodsOrderNote.getConsigneeCoordinate());
        //锁定费率
        goodsOrder.setReleasePaymentRate(shipperMemberType.getReleasePaymentRate());
        goodsOrder.setRobPaymentRate(shipperMemberType.getRobPaymentRate());
        goodsOrder.setDeliverPaymentRate(shipperMemberType.getDeliverPaymentRate());
        goodsOrder.setArrivalPaymentRate(shipperMemberType.getArrivalPaymentRate());
        if (goodsOrder.getMatching()) {
            goodsOrder.setShipperFeeRate(shipperMemberType.getShipperMatchFeeRate());
        } else {
            goodsOrder.setShipperFeeRate(shipperMemberType.getShipperCarrierFeeRate());
        }
        goodsOrder.setShipperTaxRate(shipperMemberType.getOwnerTaxRate());
        goodsOrder.setInsuranceRate(shipperMemberType.getInsuranceRate());
    }

    //### 内部保存节点信息
    private void saveNoteDetail(Account loginUser, GoodsOrder goodsOrder) {
        List<GoodsOrderNote> goodsOrderNoteList = goodsOrder.getGoodsOrderNoteList();
        List<String> measureUnits = new ArrayList<>();
        goodsOrderNoteList.forEach(goodsOrderNote -> {
            List<GoodsOrderNoteDetail> noteDetailList = goodsOrderNote.getGoodsOrderNoteDetailList();
            goodsOrderNote.setGoodsOrderId(goodsOrder.getId());
//            goodsOrderNote.setPlatId(goodsOrder.getPlatId());
//            goodsOrderNote.setPlatName(goodsOrder.getPlatName());
//            goodsOrderNote.setZonePlatId(goodsOrder.getZonePlatId());
//            goodsOrderNote.setZonePlatName(goodsOrder.getZonePlatName());
            goodsOrderNote.setAddUserId(loginUser.getId());
            goodsOrderNote.setCreateTime(new Date());
            goodsOrderNote.setGoodsNoteMeasure(ArrayUtil.numListAdd(noteDetailList, GoodsOrderNoteDetail::getGoodsMeasure));
            goodsOrderNote.setGoodsNoteTransportCost(ArrayUtil.numListAdd(noteDetailList, GoodsOrderNoteDetail::getGoodsTransportCost));
            goodsOrderNote.setGoodsNoteEmbarkMeasure(0D);
            goodsOrderNote.setMeasureUnit(goodsOrder.getMeasureUnit());
            goodsOrderNoteMapper.insert(goodsOrderNote);
            List<String> noteMeasureUnits = new ArrayList<>();
            ArrayUtil.forEach(noteDetailList, goodsNoteDetail -> {
                GoodsType goodsType = ParamUtil.isSuccess(systemRemote.getGoodsTypeById(goodsNoteDetail.getGoodsTypeId()));
                goodsNoteDetail.setGoodsOrderId(goodsOrder.getId());
                goodsNoteDetail.setGoodsOrderNoteId(goodsOrderNote.getId());
//                goodsNoteDetail.setPlatId(goodsOrder.getPlatId());
//                goodsNoteDetail.setPlatName(goodsOrder.getPlatName());
//                goodsNoteDetail.setZonePlatId(goodsOrder.getZonePlatId());
//                goodsNoteDetail.setZonePlatName(goodsOrder.getZonePlatName());
                goodsNoteDetail.setAddUserId(loginUser.getId());
                goodsNoteDetail.setCreateTime(new Date());
                goodsNoteDetail.setGoodsTypeName(goodsType.getName());
                goodsNoteDetail.setGoodsTypeCode(goodsType.getCode());
                ArrayUtil.notRepeatAdd(noteMeasureUnits, goodsNoteDetail.getMeasureUnit());
                goodsOrderNoteDetailMapper.insert(goodsNoteDetail);
            });
            ArrayUtil.notRepeatAddAll(measureUnits, noteMeasureUnits);
            goodsOrderNote.setMeasureUnit(String.join("|", noteMeasureUnits));
            goodsOrderNoteMapper.updateById(goodsOrderNote);
        });
        goodsOrder.setShipperTotalMeasure(ArrayUtil.numListAdd(goodsOrderNoteList, GoodsOrderNote::getGoodsNoteMeasure));
        goodsOrder.setUpdateTime(new Date());
        goodsOrder.setUpdateUserId(loginUser.getId());
        goodsOrder.setMeasureUnit(String.join("|", measureUnits));
        GoodsOrderNoteDetail first = ArrayUtil.first(ArrayUtil.first(goodsOrderNoteList).getGoodsOrderNoteDetailList());
        goodsOrder.setGoodsTypeName(first.getGoodsTypeName());
        goodsOrderMapper.updateById(goodsOrder);
    }

    /**
     * 内部公共 判断发货节点基础信息
     */
    private void checkGoodsOrderNote(GoodsOrderNote goodsOrderNote) {
        if (StringUtil.isEmpty(goodsOrderNote.getConsignorName())) {
            throw new BusinessException("请添加发货联系人");
        }
        if (StringUtil.isEmpty(goodsOrderNote.getConsignorPhone())) {
            throw new BusinessException("请添加发货联系人电话");
        }
        if (StringUtil.isEmpty(goodsOrderNote.getConsignorArea())) {
            throw new BusinessException("请添加发货地区");
        }
        if (StringUtil.isEmpty(goodsOrderNote.getConsignorCoordinate())) {
            throw new BusinessException("请添加发货地坐标");
        }
        if (StringUtil.isEmpty(goodsOrderNote.getConsigneeName())) {
            throw new BusinessException("请添加收货联系人");
        }
        if (StringUtil.isEmpty(goodsOrderNote.getConsigneePhone())) {
            throw new BusinessException("请添加收货联系人电话");
        }
        if (StringUtil.isEmpty(goodsOrderNote.getConsigneeArea())) {
            throw new BusinessException("请添加收货地区");
        }
        if (StringUtil.isEmpty(goodsOrderNote.getConsigneeCoordinate())) {
            throw new BusinessException("请添加收货节地坐标");
        }
    }

    /**
     * 内部公共 判断货物节点信息
     */
    private void checkGoodsInfo(GoodsOrder goodsOrder, GoodsOrderNoteDetail goodsOrderNoteDetail) {
        if (StringUtil.isEmpty(goodsOrderNoteDetail.getGoodsTypeId())) {
            throw new BusinessException("请选择货物类型");
        }
        if (StringUtil.isEmpty(goodsOrderNoteDetail.getGoodsName())) {
            throw new BusinessException("请输入货物名称");
        }
        if (goodsOrderNoteDetail.getGrossWeight() == null || goodsOrderNoteDetail.getGrossWeight() < 0) {
            throw new BusinessException("请提供或估值货物毛重");
        }
        if (StringUtil.isEmpty(goodsOrderNoteDetail.getMeasureUnit())) {
            throw new BusinessException("单位出错，请检查货物计量单位");
        }
        if (goodsOrderNoteDetail.getGoodsMeasure() == null || goodsOrderNoteDetail.getGoodsMeasure() < 0) {
            throw new BusinessException("请提供货物量,单位:" + goodsOrderNoteDetail.getMeasureUnit());
        }
        if (goodsOrder.getPriceMode() == GoodsOrder.PriceMode.unitPrice && (goodsOrderNoteDetail.getGoodsUnitPrice() == null || goodsOrderNoteDetail.getGoodsUnitPrice() <= 0)) {
            throw new BusinessException("单价计价模式下，请填写货物运输单价");
        }
    }

    /**
     * 内部 计算货源费用,包括手续费，运输费，保费等
     */
    private void calculateOrderCost(GoodsOrder goodsOrder) {
        String startLngLats = ArrayUtil.fieldAddStrJoin(goodsOrder.getGoodsOrderNoteList(), GoodsOrderNote::getConsignorCoordinate, ";");
        String endLngLats = ArrayUtil.fieldAddStrJoin(goodsOrder.getGoodsOrderNoteList(), GoodsOrderNote::getConsigneeCoordinate, ";");
        CalculateCost calculateCost = calculationService.getShipperCalculateCost(goodsOrder.getShipperOrganizeId(), goodsOrder.getPriceMode(), goodsOrder.getShipperTransportCost(), startLngLats, endLngLats, goodsOrder.getTruckTypeIds(), goodsOrder.getMatching(), goodsOrder.getIncludedTax());
        goodsOrder.setKilometer(CommonUtil.doubleTwo(calculateCost.getDistance() / 1000));//Distance单位是米
        goodsOrder.setDuration((int) calculateCost.getDuration());
        try {
            //防止前台篡改数据，这里也不覆盖，直接拦截返回
            ParamUtil.notEquals("运费前后计算不一致", calculateCost.getFreight(), goodsOrder.getShipperTransportCost());
            ParamUtil.notEquals("服务费前后计算不一致", calculateCost.getFeeCost(), goodsOrder.getShipperServiceCost());
            ParamUtil.notEquals("额外税费前后计算不一致", calculateCost.getExtraTaxCost(), goodsOrder.getShipperTaxCost());
        } catch (RuntimeException e) {
            logger.error(String.format("货源：%s计算货源费用出错，%s", goodsOrder.getGoodsOrderNo(), e.getMessage()));
        }
    }

}
